﻿﻿using System;
using System.Text.RegularExpressions;

namespace M
{
	/// <summary>
	/// M参数校验类
	/// 此类校验失败时，将抛出原生异常，请根据具体业务逻辑处理MException
	/// </summary>
	public static class MValidator
	{
		/// <summary>
		/// 检查是否为空引用
		/// </summary>
		/// <param name="name">参数名称</param>
		/// <param name="value">参数值</param>
		public static void CheckForNullReference(string name, object value)
		{
			if (name == null)
			{
				throw new MException("参数名不能为空", MExceptionLevel.Stop, new ArgumentNullException(string.Format("Param Name:{0}", name)));
			}
			if (value == null)
			{
				throw new MException("参数不能为空", MExceptionLevel.Stop, new ArgumentNullException(name));
			}
		}

		/// <summary>
		/// 检查字符串是否为空字符串
		/// </summary>
		/// <param name="name">参数名称</param>
		/// <param name="value">参数值</param>
		public static void CheckForEmptyString(string name, string value)
		{
			CheckForNullReference("CheckForString: text", name);
			CheckForNullReference(name, value);
			if (value.Length == 0)
				throw new MException("参数不能为空", MExceptionLevel.Stop, new ArgumentNullException(name));
		}
		/// <summary>
		/// 检查GUID是否为空
		/// </summary>
		/// <param name="name">参数名称</param>
		/// <param name="guid">guid</param>
		public static void CheckForEmptyGUID(string name, Guid guid)
		{
			CheckForNullReference(name, guid);
			if (guid.CompareTo(Guid.Empty) == 0)
				throw new MException("参数不能为空", MExceptionLevel.Stop, new ArgumentNullException(name));
		}

		/// <summary>
		/// 检查是否为期望类型
		/// </summary>
		/// <param name="type">类型参数</param>
		/// <param name="value">类型值</param>
		public static void CheckExpectedType(Type type, object value)
		{
			CheckForNullReference("value", value);
			CheckForNullReference("type", type);
			if (!type.IsAssignableFrom(value.GetType()))
				throw new MException("参数类型不正确", MExceptionLevel.Stop, new ArgumentException("mismatched type", type.ToString()));
		}

		/// <summary>
		/// 检查是否为有效的枚举值
		/// </summary>
		/// <param name="type">枚举类型</param>
		/// <param name="name">参数名称</param>
		/// <param name="value">参数值</param>
		public static void CheckEnumeration(Type type, string name, object value)
		{
			CheckForNullReference("type", type);
			CheckForNullReference("value", value);
			CheckForNullReference("text", name);
			if (!Enum.IsDefined(type, value))
				throw new MException("参数为无效枚举", MExceptionLevel.Stop, new ArgumentException("undefined enumeration", string.Format("{0}:{1} {2}", type, name, value)));
		}

		/// <summary>
		/// 检查指定值是否超出边界
		/// </summary>
		/// <typeparam name="T">类型</typeparam>
		/// <param name="name">参数名称</param>
		/// <param name="value">参数值</param>
		/// <param name="min">最小值</param>
		/// <param name="max">最大值</param>
		public static void CheckValueLimit<T>(string name, T value, T min, T max) where T : IComparable
		{
			CheckForNullReference("text", name);
			if (value.CompareTo(min) < 0)
				throw new MException("参数小于最小边界", MExceptionLevel.Stop, new ArgumentOutOfRangeException(name));
			if (value.CompareTo(max) > 0)
				throw new MException("参数大于最大边界", MExceptionLevel.Stop, new ArgumentOutOfRangeException(name));
		}

		/// <summary>
		/// 检查指定值是否超过最大值
		/// </summary>
		/// <typeparam name="T">类型</typeparam>
		/// <param name="name">参数名称</param>
		/// <param name="value">参数值</param>
		/// <param name="max">最大值</param>
		public static void CheckValueMaxLimit<T>(string name, T value, T max) where T : IComparable
		{
			CheckForNullReference("paraName", name);
			if (value.CompareTo(max) > 0)
				throw new MException("参数大于最大边界", MExceptionLevel.Stop, new ArgumentOutOfRangeException(name));
		}

		/// <summary>
		/// 检查指定值是否小于最小值
		/// </summary>
		/// <typeparam name="T">类型</typeparam>
		/// <param name="name">参数名称</param>
		/// <param name="value">参数值</param>
		/// <param name="min">最小值</param>
		public static void CheckValueMinLimit<T>(string name, T value, T min) where T : IComparable
		{
			CheckForNullReference("text", name);
			if (value.CompareTo(min) < 0)
				throw new MException("参数小于最小边界", MExceptionLevel.Stop, new ArgumentOutOfRangeException(name));
		}
	}
}
